<script setup lang="ts">
import { useConversationStore } from '@/stores/conversation'
import { RecordRole, type RecordItem } from '@/types'
import { ref, nextTick, onMounted, watch } from 'vue'
import RecordItemContainer from './RecordItem.vue'
import { useToast } from 'vue-toastification'
import { useGoTo } from 'vuetify'

withDefaults(
  defineProps<{
    noToggle?: boolean
  }>(),
  {
    noToggle: false,
  },
)

const emit = defineEmits<{
  toggleDrawShow: []
  backHome: []
}>()

const goTo = useGoTo()

const toast = useToast()
const conversationStore = useConversationStore()

const firstLoad = ref(true)
const isBottom = ref(true)
const inputValue = ref('')
const recordList = ref<RecordItem[]>([])

onMounted(() => {
  init()
  loadDataByKey()
})

watch(
  () => conversationStore.currentKey,
  () => {
    init()
    loadDataByKey()
  },
)

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const handleScroll = (el: any) => {
  const clientHeight = el.target.clientHeight
  const scrollHeight = el.target.scrollHeight
  const scrollTop = el.target.scrollTop
  if (Math.ceil(scrollTop) + Math.ceil(clientHeight) >= scrollHeight) {
    console.log('到底了!')
    isBottom.value = true
  } else {
    isBottom.value = false
  }
}

const init = () => {
  inputValue.value = ''
  recordList.value = []
  conversationStore.messageFirstId = ''
  if (!conversationStore.getCurrent?.id) {
    recordList.value = [
      { answer: conversationStore.getCurrent?.introduction, role: RecordRole.assistant },
    ]
  }
}

const loadDataByKey = async () => {
  if (!conversationStore.getCurrent) {
    emit('backHome')
    return
  }
  const res = await conversationStore.getConversationMessages()
  if (!res) {
    return
  }
  if (res.data) {
    const list = []
    for (const item of res.data) {
      const query = {
        query: item.query,
        conversation_id: item.conversation_id,
        id: item.id,
        role: RecordRole.user,
      }
      const answer = {
        query: item.query,
        answer: item.answer,
        error: item.error,
        conversation_id: item.conversation_id,
        id: item.id,
        role: RecordRole.assistant,
        status: item.status,
      }
      list.push(...[query, answer])
    }
    recordList.value = [...list, ...recordList.value]
    if (firstLoad.value) {
      firstLoad.value = false
      nextTick(() => {
        handleScrollToBottom()
      })
    }
  }
}

const handleToggleDrawShow = () => {
  emit('toggleDrawShow')
}

const handleSendMessage = () => {
  if (!inputValue.value) return
  if (conversationStore.isAnswering) {
    toast('请等待回答完成')
    return
  }
  const query = inputValue.value
  recordList.value.push(
    ...[
      { query, role: RecordRole.user },
      { query, role: RecordRole.assistant },
    ],
  )
  inputValue.value = ''
  nextTick(() => {
    handleScrollToBottom()
  })
}

const handleAnswerUpdate = () => {
  nextTick(() => {
    handleScrollToBottom()
  })
}

const handleScrollToBottom = (smooth?: boolean) => {
  const scrollContainer = document.getElementById('conversation-record-container') as HTMLElement
  if (!scrollContainer) return
  if (smooth) {
    goTo(scrollContainer.scrollHeight, {
      container: '#conversation-record-container',
    })
  } else {
    scrollContainer.scrollTop = scrollContainer.scrollHeight
  }
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const handleInfiniteLoad = async ({ done }: any) => {
  await loadDataByKey()
  if (conversationStore.messageHasMore) {
    done('ok')
  } else {
    done('empty')
    if (!conversationStore.isNew) {
      recordList.value = [
        {
          answer: conversationStore.getCurrent?.introduction,
          role: RecordRole.assistant,
        },
        ...recordList.value,
      ]
    }
  }
}
</script>

<template>
  <template v-if="conversationStore.getCurrent">
    <v-app-bar :title="conversationStore.getCurrent.name">
      <template v-slot:prepend>
        <v-app-bar-nav-icon
          v-if="$vuetify.display.mobile && !noToggle"
          @click.stop="handleToggleDrawShow"
        ></v-app-bar-nav-icon>
      </template>
      <template v-slot:append>
        <slot></slot>
      </template>
    </v-app-bar>
    <v-main class="!flex flex-col">
      <div class="flex-auto h-0 relative">
        <v-fab
          :active="!isBottom"
          class="fab-button"
          icon="mdi-arrow-down"
          color="primary"
          location="right bottom"
          transition="slide-y-reverse-transition"
          absolute
          @click="handleScrollToBottom(true)"
        ></v-fab>
        <v-infinite-scroll
          id="conversation-record-container"
          class="!p-4"
          side="start"
          height="100%"
          empty-text="没有更多了"
          @load="handleInfiniteLoad"
          @scroll="handleScroll"
          v-if="recordList.length"
        >
          <record-item-container
            v-for="(item, index) in recordList"
            :key="index"
            :item="item"
            @answer-update="handleAnswerUpdate"
          ></record-item-container>
          <template v-slot:empty>
            <v-alert type="warning" v-if="recordList.length > 1 && !conversationStore.isNew"
              >没有更多了！</v-alert
            >
          </template>
        </v-infinite-scroll>
      </div>
      <div
        class="flex-[0_0_auto]"
        :class="`${$vuetify.display.mobile ? 'border-t border-solid border-grey bg-[#F5F5F5]' : '!px-16 !py-4'}`"
      >
        <div
          :class="`${$vuetify.display.mobile ? 'flex content-center align-center !p-2' : 'w-full flex align-center border border-solid border-grey rounded-md shadow-lg !p-2'}`"
        >
          <v-text-field
            :class="`${$vuetify.display.mobile ? '' : 'input'}`"
            v-model="inputValue"
            hide-details
            single-line
            variant="solo"
            density="comfortable"
            clearable
            placeholder="请输入文字..."
            @keyup.enter="handleSendMessage"
          />
          <v-btn
            class="!ml-2"
            :readonly="conversationStore.isAnswering"
            color="primary"
            icon="mdi-send"
            @click.stop="handleSendMessage"
          />
        </div>
      </div>
    </v-main>
  </template>
</template>

<style lang="scss" scoped>
.input {
  ::v-deep(.v-field) {
    box-shadow: none;
  }
}
.record-item + .record-item {
  margin-top: 10px;
}
.fab-button {
  ::v-deep(.v-fab__container) {
    margin: 16px;
  }
}
</style>
